Java 中的继承和组合

好久没更新Blog了,翻出过往的笔记,决定补充下 Java 部分的文章,鉴于目前的数量还不是很多,还是继续补充基础知识吧。

今天记录一下Java 中的 继承 和 组合,即 Inheritance VS Composition 。

继承

继承是一种子类是父类的关系,即所谓的 is-a 关系,它描述,子类是一种父类。

先上个代码:

class A {
    public void funcX() {
        System.out.println("This is funcX of Class A");
    }
    public void funcY() {
        funcX();
        System.out.println("This is funcY of Class A");
    }
}

class B extends A {
    public void funcX() {
        System.out.println("This is funcX of Class B");
    }
    public void funcY() {
        funcX();
        super.funcY();
    }
}

子类继承父类,子类具有父类完全的能力,能调用父类的方法,能重写方法,这里的重写方法,有另外一个概念,就是扩充父类方法,比如子类中的 super.funcY(), 这句其实是调用父类的方法,也就是说,子类有某种能力是基于父类的能力,并且,将父类的能力扩充。 所以,从这点上来讲,如果重写一个方法,和父类的方法完全不相干的,那么,从设计理念上看,就不是很合适。

因此,出现了组合

组合

interface IA {
    public void funcX();
}

class AImpl implements IA {
    private String whoAmI;
    public AImpl(String whoAmI) {
        this.whoAmI = whoAmI;
    }
    public void funcX() {
        System.out.println("This is funcX of " + whoAmI);
    }
}

class Abc {
}

class Def extends Abc implement IA {
    private IA ia;
    public Def(IA ia) {
        this.ia = ia;
    }
    public void funcX() {
        ia.funcX();
    }
}

class Sample {
    public static void main(String[] args) {
        Def sample = new Def(new AImpl("Jacky"));
        Def sample2 = new Def(new AImpl("Spider Man"));
    }
}

从这段代码看,AI 接口抽象了某种能力,AImpl 实现了这种能力,并以参数形式区别,所以不管 父类 Abc 还是 子类 Def, 使用不同参数,达到了不同效果,也不影响继承关系,比如子类父类都有某个方法,子类重写了,里面的某个功能都是需要用到了,而且有点区别,这个时候就可以用接口。

那么这种组合的接口的好处是什么呢? 可能不够简单,画个类图,篇幅也多,为何如此呢?

这要从 Java 的设计理念来看,Java 属于学院派,重点是要把事情说清楚,并且在某一段时间内,达到很好的可扩展,只增加,不修改。所以,设计还是比较讲究的。